//
//  UnidirectionalBindDispose.swift
//  CSBind
//
//  Created by 万孟超 on 2023/12/22.
//

import Foundation


/// 单向绑定垃圾回收站
/// 一个回收站实例只能产生一个绑定事件
/// 再次绑定之后，第一次绑定将失效
public class CSUnidirectionalBindDispose: CSBindDispose {
    /// 绑定操作者
    private var bindOperator: CSBindOperatorRelease?
    
    // MARK -- 被绑定者keyPath为String类型，绑定者的keyPath为keyPath类型
    
    /// 单向绑定
    /// - Parameters:
    ///   - target: 被绑定者 监听值改变者
    ///   - targetKeyPath: 被绑定者的键值String
    ///   - binder: 绑定者 绑定者的值随着被绑定者的变化而变化
    ///   - binderKeyPath: 绑定者的键值KeyPath
    /// - Returns: 单向绑定回收站
    public class final func bind<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: String, _ binder: RT?, _ binderKeyPath: ReferenceWritableKeyPath<RT, ValueType>) -> Self where LT: NSObject, RT: NSObject, ValueType: Any {
        let ability = CSUnidirectionalBindDispose()
        ability.bind(target, targetKeyPath, binder, binderKeyPath)
        return ability as! Self
    }
    
    /// 单向绑定
    /// - Parameters:
    ///   - target: 被绑定者 监听值改变者
    ///   - targetKeyPath: 被绑定者的键值String
    ///   - binder: 绑定者 绑定者的值随着被绑定者的变化而变化
    ///   - binderKeyPath: 绑定者的键值KeyPath
    public override func bind<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: String, _ binder: RT?, _ binderKeyPath: ReferenceWritableKeyPath<RT, ValueType>) where LT: NSObject, RT: NSObject, ValueType: Any {
        free()
        bindOperator = create(target, targetKeyPath, binder, binderKeyPath) as? any CSBindOperatorRelease
    }
    
    // MARK -- 被绑定者keyPath为keyPath类型，绑定者的keyPath为String类型
    
    /// 单向绑定 
    /// - Parameters:
    ///   - target: 被绑定者 监听值改变者
    ///   - targetKeyPath: 被绑定者的键值KeyPath
    ///   - binder: 绑定者 绑定者的值随着被绑定者的变化而变化
    ///   - binderKeyPath: 绑定者的键值string
    /// - Returns: 单向绑定回收站
    public class final func bind<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ binder: RT?, _ binderKeyPath: String) -> Self where LT: NSObject, RT: NSObject, ValueType: Any {
        let ability = CSUnidirectionalBindDispose()
        ability.bind(target, targetKeyPath, binder, binderKeyPath)
        return ability as! Self
    }
    
    /// 单向绑定
    /// - Parameters:
    ///   - target: 被绑定者 监听值改变者
    ///   - targetKeyPath: 被绑定者的键值KeyPath
    ///   - binder: 绑定者 绑定者的值随着被绑定者的变化而变化
    ///   - binderKeyPath: 绑定者的键值string
    public override func bind<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ binder: RT?, _ binderKeyPath: String) where LT: NSObject, RT: NSObject, ValueType: Any {
        free()
        bindOperator = create(target, targetKeyPath, binder, binderKeyPath) as? any CSBindOperatorRelease
    }
    
    // MARK -- 被绑定者keyPath为keyPath类型，绑定者的keyPath为keyPath类型
    
    /// 单向绑定
    /// - Parameters:
    ///   - target: 被绑定者 监听值改变者
    ///   - targetKeyPath: 被绑定者的键值String
    ///   - binder: 绑定者 绑定者的值随着被绑定者的变化而变化
    ///   - binderKeyPath: 绑定者的键值KeyPath
    /// - Returns: 单向绑定回收站
    public class final func bind<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ binder: RT?, _ binderKeyPath: ReferenceWritableKeyPath<RT, ValueType>) -> Self where LT: NSObject, RT: NSObject, ValueType: Any {
        let ability = CSUnidirectionalBindDispose()
        ability.bind(target, targetKeyPath, binder, binderKeyPath)
        return ability as! Self
    }
    
    /// 单向绑定
    /// - Parameters:
    ///   - target: 被绑定者
    ///   - targetKeyPath: 被绑定者的键值KeyPath
    ///   - binder: 绑定者
    ///   - binderKeyPath: 绑定者的键值KeyPath
    public override func bind<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ binder: RT?, _ binderKeyPath: ReferenceWritableKeyPath<RT, ValueType>) where LT: NSObject, RT: NSObject, ValueType: Any {
        free()
        bindOperator = create(target, targetKeyPath, binder, binderKeyPath) as? any CSBindOperatorRelease
    }
    
    
    // MARK -- 被绑定者keyPath为String类型，绑定者的keyPath为String类型
    
    /// 单向绑定
    /// - Parameters:
    ///   - target: 被绑定者 监听值改变者
    ///   - targetKeyPath: 被绑定者的键值String
    ///   - binder: 绑定者 绑定者的值随着被绑定者的变化而变化
    ///   - binderKeyPath: 绑定者的键值KeyPath
    /// - Returns: 单向绑定回收站
    public class final func bind<LT, RT>(_ target: LT?, _ targetKeyPath: String, _ binder: RT?, _ binderKeyPath: String) -> Self where LT: NSObject, RT: NSObject {
        let ability = CSUnidirectionalBindDispose()
        ability.bind(target, targetKeyPath, binder, binderKeyPath)
        return ability as! Self
    }
    
    /// 单向绑定
    /// - Parameters:
    ///   - target: 被绑定者 监听值改变者
    ///   - targetKeyPath: 被绑定者的键值String
    ///   - binder: 绑定者 绑定者的值随着被绑定者的变化而变化
    ///   - binderKeyPath: 绑定者的键值KeyPath
    public override func bind<LT, RT>(_ target: LT?, _ targetKeyPath: String, _ binder: RT?, _ binderKeyPath: String) where LT: NSObject, RT: NSObject {
        free()
        bindOperator = create(target, targetKeyPath, binder, binderKeyPath) as? any CSBindOperatorRelease
    }
    
    /// 取消绑定
    public override func free() {
        bindOperator?.free()
        bindOperator = nil
    }
    
    /// 暂停绑定
    /// 暂时停止绑定，和`run`可以配套使用
    public override func pause() {
        bindOperator?.pause()
    }
    
    /// 启动绑定
    /// 绑定暂停后，调用此方法可以重新启动绑定
    public override func run() {
        bindOperator?.run()
    }
    
    /// 刷新是否忽略相同值
    override func freshIgnoreSameValue() {
        bindOperator?.freshIgnoreSameValue(isIgnoreSameValue)
    }
    
    override func updateIgnoreTimes() {
        bindOperator?.updateIgnoreTimes(bindIgnoreTimes)
    }
    
    override func updateBindIgnoreTimesByIgnoreValue() {
        bindOperator?.updateBindIgnoreTimesByIgnoreValue(bindIgnoreTimesByIgnoreValue)
    }
    
    /// 立即生效一次
    public override func immediatelyAvaliable() {
        bindOperator?.immediatelyExcute()
    }
}

extension CSUnidirectionalBindDispose: CSOperatorBindable { }
